home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / tde3.zip / MAIN.C < prev    next >
C/C++ Source or Header  |  1993-06-05  |  15KB  |  532 lines

  1. /*******************  start of original comments  ********************/
  2. /*
  3.  * Written by Douglas Thomson (1989/1990)
  4.  *
  5.  * This source code is released into the public domain.
  6.  */
  7.  
  8. /*
  9.  * Name:    dte - Doug's Text Editor program - hardware dependent module
  10.  * Purpose: This file contains all the code that needs to be different on
  11.  *           different hardware.
  12.  * File:    hwibm.c
  13.  * Author:  Douglas Thomson
  14.  * System:  This particular version is for the IBM PC and close compatibles.
  15.  *           It write directly to video RAM, so it is faster than other
  16.  *           techniques, but will cause "snow" on most CGA cards. See the
  17.  *           file "hwibmcga.c" for a version that avoids snow.
  18.  *          The compiler is Turbo C 2.0, using one of the large data memory
  19.  *           models.
  20.  * Date:    October 10, 1989
  21.  * Notes:   This module has been kept as small as possible, to facilitate
  22.  *           porting between different systems.
  23.  */
  24. /*********************  end of original comments   ********************/
  25.  
  26.  
  27. /*
  28.  * These routines were rewritten for Microsoft C.  They are pretty much system
  29.  * dependent and pretty much Microsoft C dependent.  I also renamed this file
  30.  * "main.c" - easier to find the main function.
  31.  *
  32.  * New editor name:  TDE, the Thomson-Davis Editor.
  33.  * Author:           Frank Davis
  34.  * Date:             June 5, 1991, version 1.0
  35.  * Date:             July 29, 1991, version 1.1
  36.  * Date:             October 5, 1991, version 1.2
  37.  * Date:             January 20, 1992, version 1.3
  38.  * Date:             February 17, 1992, version 1.4
  39.  * Date:             April 1, 1992, version 1.5
  40.  * Date:             June 5, 1992, version 2.0
  41.  * Date:             October 31, 1992, version 2.1
  42.  * Date:             April 1, 1993, version 2.2
  43.  * Date:             June 5, 1993, version 3.0
  44.  *
  45.  * This modification of Douglas Thomson's code is released into the
  46.  * public domain, Frank Davis.  You may distribute it freely.
  47.  */
  48.  
  49.  
  50. char *greatest_composer_ever = "W. A. Mozart, 1756-1791";
  51.  
  52.  
  53. #include "tdestr.h"             /* tde types */
  54. #include "common.h"
  55. #include "define.h"
  56. #include "help.h"
  57. #include "tdefunc.h"
  58.  
  59.  
  60. #include <dos.h>                /* for renaming files */
  61. #include <bios.h>               /* for direct BIOS keyboard input */
  62. #include <io.h>                 /* for file attribute code */
  63. #include <fcntl.h>              /* open flags */
  64. #if defined( __MSC__ )
  65.    #include <errno.h>
  66.    #include <sys\types.h>       /* S_IWRITE etc */
  67. #endif
  68. #include <sys\stat.h>           /* S_IWRITE etc */
  69.  
  70. #if defined( __MSC__ )
  71. void (interrupt far *old_control_c)( ); /* variable for old CNTL-C */
  72. void (interrupt far *old_int1b)( );     /* variable for old int 1b */
  73. #endif
  74.  
  75.  
  76. /*
  77.  * original control-break checking flag
  78.  */
  79. static int s_cbrk;
  80.  
  81.  
  82. /*
  83.  * Name:    main
  84.  * Purpose: To do any system dependent command line argument processing,
  85.  *           and then call the main editor function.
  86.  * Date:    October 10, 1989
  87.  * Passed:  argc:   number of command line arguments
  88.  *          argv:   text of command line arguments
  89.  */
  90. void main( int argc, char *argv[] )
  91. {
  92. #if defined( __MSC__ )
  93.    union REGS inregs, outregs;
  94. #endif
  95.  
  96.    g_status.found_first = FALSE;
  97.    g_status.arg         = 1;
  98.    g_status.argc        = argc;
  99.    g_status.argv        = argv;
  100.  
  101.    /*
  102.     * trap control-break to make it harmless, and turn checking off.
  103.     *   trap control-C to make it harmless.
  104.     */
  105. #if defined( __MSC__ )
  106.    inregs.h.ah = 0x33;
  107.    inregs.h.al = 0;
  108.    intdos( &inregs, &outregs );
  109.    s_cbrk = outregs.h.dl;
  110.    old_control_c = _dos_getvect( (unsigned)0x23 );
  111.    _dos_setvect( 0x23, harmless );
  112.    old_int1b = _dos_getvect( (unsigned)0x1b );
  113.    _dos_setvect( 0x1b, ctrl_break );
  114.    inregs.h.ah = 0x33;
  115.    inregs.h.al = 1;
  116.    inregs.h.dl = 0;
  117.    intdos( &inregs, &outregs );
  118. #else
  119.    s_cbrk = getcbrk( );
  120.    ctrlbrk( harmless );
  121.    setcbrk( 0 );
  122. #endif
  123.  
  124.  
  125.    /*
  126.     * now, install and initialize our simple Critical Error Handler.
  127.     */
  128.    install_ceh( &ceh );
  129.    ceh.flag = OK;
  130.  
  131.    initialize( );
  132.    editor( );
  133.    terminate( );
  134. }
  135.  
  136.  
  137. /*
  138.  * Name:    error
  139.  * Purpose: To report an error, and usually make the user type <ESC> before
  140.  *           continuing.
  141.  * Date:    June 5, 1991
  142.  * Passed:  kind:   an indication of how serious the error was:
  143.  *                      WARNING: continue after pressing a key
  144.  *                      FATAL:   abort the editor
  145.  *          line:    line to display message
  146.  *          message: string to be printed
  147.  * Notes:   Show user the message and ask for a key if needed.
  148.  */
  149. void error( int kind, int line, char *message )
  150. {
  151. char buff[MAX_COLS+2];          /* somewhere to store error before printing */
  152. char line_buff[(MAX_COLS+2)*2]; /* buffer for char and attribute  */
  153.  
  154.    /*
  155.     * tell the user what kind of an error it is
  156.     */
  157.    switch (kind) {
  158.       case FATAL:
  159.          /*
  160.           * fatal error
  161.           */
  162.          assert( strlen( main1 ) < MAX_COLS );
  163.          strcpy( buff, main1 );
  164.          break;
  165.      case WARNING:
  166.      default:
  167.          /*
  168.           * warning
  169.           */
  170.          assert( strlen( main2 ) < MAX_COLS );
  171.          strcpy( buff, main2 );
  172.          break;
  173.    }
  174.  
  175.    /*
  176.     * prepare the error message itself
  177.     */
  178.    strcat( buff, message );
  179.  
  180.    /*
  181.     * tell the user how to continue editing if necessary
  182.     */
  183.    if (kind == WARNING)
  184.       /*
  185.        * press a key
  186.        */
  187.       strcat( buff, main3 );
  188.  
  189.    /*
  190.     * output the error message
  191.     */
  192.    save_screen_line( 0, line, line_buff );
  193.    set_prompt( buff, line );
  194.  
  195.    if (kind == FATAL) {
  196.       /*
  197.        * no point in making the user type <ESC>, since the program is
  198.        *  about to abort anyway...
  199.        */
  200.       terminate( );
  201.       exit( 1 );
  202.    }
  203.  
  204.    getkey( );
  205.    restore_screen_line( 0, line, line_buff );
  206.    if (g_status.wrapped) {
  207.       g_status.wrapped = FALSE;
  208.       show_search_message( CLR_SEARCH, g_display.mode_color );
  209.    }
  210. }
  211.  
  212.  
  213. /*
  214.  * Name:    harmless
  215.  * Purpose: Do nothing when control-C is pressed
  216.  * Date:    June 5, 1991
  217.  * Notes:   Interrupt 23, the Control-C handler, is a MS DOS system function.
  218.  *            Since we want to use Control-C as a regular function key,
  219.  *            let's do absolutely nothing when Control-C is pressed.
  220.  */
  221. #if defined( __MSC__ )
  222. void interrupt far harmless( void )
  223. #else
  224. static int harmless( void )
  225. #endif
  226. {
  227. }
  228.  
  229.  
  230. /*
  231.  * Name:    ctrl_break
  232.  * Purpose: Set our control-break flag when control-break is pressed.
  233.  * Date:    June 5, 1992
  234.  * Notes:   Control-break is a little different from Control-C.  When
  235.  *           Control-C is pressed, MS DOS processes it as soon as possible,
  236.  *           which may be quite a while.  On the other hand, when
  237.  *           Control-break is pressed on IBM and compatibles, interrupt 0x1b
  238.  *           is generated immediately.  Since an interrupt is generated
  239.  *           immediately, we can gain control of run-away functions, like
  240.  *           recursive macros, by checking our Control-break flag.
  241.  */
  242. void interrupt far ctrl_break( void )
  243. {
  244.    g_status.control_break = TRUE;
  245. }
  246.  
  247.  
  248. /*
  249.  * Name:    terminate
  250.  * Purpose: To free all dynamic structures and unload anything we loaded
  251.  * Date:    June 5, 1991
  252.  */
  253. void terminate( void )
  254. {
  255. union REGS inregs, outregs;
  256. register WINDOW     *wp;        /* register for scanning windows */
  257. WINDOW              *w;         /* free window */
  258. register file_infos *fp;        /* register for scanning files */
  259. file_infos          *f;         /* free files */
  260. int                 i;
  261.  
  262.    /*
  263.     * restore control-break checking
  264.     */
  265. #if defined( __MSC__ )
  266.    _dos_setvect( 0x1b, old_int1b );
  267.    _dos_setvect( 0x23, old_control_c );
  268.    inregs.h.ah = 0x33;
  269.    inregs.h.al = 1;
  270.    inregs.h.dl = (char)s_cbrk;
  271.    intdos( &inregs, &outregs );
  272. #else
  273.    setcbrk( s_cbrk );
  274. #endif
  275.  
  276.    /*
  277.     * free the file structures, if not already free.
  278.     */
  279.    fp = g_status.file_list;
  280.    while (fp != NULL) {
  281.       f  = fp;
  282.       fp = fp->next;
  283.       free( f );
  284.    }
  285.  
  286.    /*
  287.     * free the window structures, if not already free.
  288.     */
  289.    wp = g_status.window_list;
  290.    while (wp != NULL) {
  291.       w  = wp;
  292.       wp = wp->next;
  293.       free( w );
  294.    }
  295.  
  296.  
  297.    /*
  298.     * free any character classes in the nfa's.
  299.     */
  300.    for (i=0; i < REGX_SIZE; i++) {
  301.       if (sas_nfa.class[i] == nfa.class[i]  &&  nfa.class[i] != NULL)
  302.          free( nfa.class[i] );
  303.       else if (sas_nfa.class[i] != NULL)
  304.          free( sas_nfa.class[i] );
  305.       else if (nfa.class[i] != NULL)
  306.          free( nfa.class[i] );
  307.    }
  308.  
  309.  
  310.    /*
  311.     * reset the cursor size and unload the 83/84 key keyboard utility
  312.     */
  313.    set_cursor_size( mode.cursor_size == SMALL_INS ? g_display.insert_cursor :
  314.                                                     g_display.overw_cursor );
  315.    if (mode.enh_kbd == FALSE)
  316.       simulate_enh_kbd( 0 );
  317.  
  318.    /*
  319.     * restore the overscan (border) color
  320.     */
  321.    if (g_display.adapter != MDA)
  322.       set_overscan_color( g_display.old_overscan );
  323. }
  324.  
  325.  
  326. /*
  327.  * Name:    initialize
  328.  * Purpose: To initialize all the screen status info that is not hardware
  329.  *           dependent, and call the hardware initialization routine to
  330.  *           pick up the hardware dependent stuff.
  331.  * Date:    June 5, 1991
  332.  * Returns: [g_status and g_display]: all set up ready to go
  333.  * Notes:   It is assumed that g_status and g_display are all \0's to begin
  334.  *           with (the default if they use static storage). If this may
  335.  *           not be the case, then clear them explicitly here.
  336.  */
  337. void initialize( void )
  338. {
  339. int i;
  340.  
  341.    /*
  342.     * do the hardware initialization first.
  343.     */
  344.    hw_initialize( );
  345.  
  346.    /*
  347.     * now, initialize the editor modes, pointers, and counters.
  348.     */
  349.    bm.search_defined        = ERROR;
  350.    sas_bm.search_defined    = ERROR;
  351.    g_status.sas_defined     = ERROR;
  352.    g_status.sas_search_type = ERROR;
  353.  
  354.    regx.search_defined      = ERROR;
  355.    sas_regx.search_defined  = ERROR;
  356.  
  357.    if (mode.undo_max < 2)
  358.       mode.undo_max = 2;
  359.  
  360.    g_status.marked_file = NULL;
  361.    g_status.current_window = NULL;
  362.    g_status.current_file = NULL;
  363.    g_status.window_list = NULL;
  364.    g_status.file_list = NULL;
  365.    g_status.buff_node = NULL;
  366.  
  367.    g_status.window_count = 0;
  368.    g_status.file_count = 0;
  369.    g_status.line_buff_len = 0;
  370.    g_status.tabout_buff_len = 0;
  371.    g_status.command = 0;
  372.    g_status.key_pressed = 0;
  373.    g_status.sas_rcol  = 0;
  374.    g_status.sas_rline = 0;
  375.    g_status.recording_key = 0;
  376.  
  377.    g_status.key_pending = FALSE;
  378.    g_status.found_first = FALSE;
  379.    g_status.sas_found_first = FALSE;
  380.    g_status.copied = FALSE;
  381.    g_status.wrapped = FALSE;
  382.    g_status.marked = FALSE;
  383.    g_status.macro_executing = FALSE;
  384.    g_status.replace_defined = FALSE;
  385.  
  386.    g_status.screen_display = TRUE;
  387.  
  388.    g_status.file_chunk = DEFAULT_BIN_LENGTH;
  389.  
  390.    g_status.sas_tokens[0] = '\0';
  391.    g_status.path[0] = '\0';
  392.    g_status.sas_path[0] = '\0';
  393.    g_status.rw_name[0] = '\0';
  394.    g_status.pattern[0] = '\0';
  395.    g_status.subst[0] = '\0';
  396.  
  397.  
  398.    /*
  399.     * set the number of lines from one page that should still be visible
  400.     *  on the next page after page up or page down.
  401.     */
  402.    g_status.overlap = 1;
  403.  
  404.  
  405.    /*
  406.     * initialize the nodes in the nfa.
  407.     */
  408.    for (i=0; i < REGX_SIZE; i++) {
  409.       sas_nfa.node_type[i] = nfa.node_type[i] = 0;
  410.       sas_nfa.term_type[i] = nfa.term_type[i] = 0;
  411.       sas_nfa.c[i] = nfa.c[i] = 0;
  412.       sas_nfa.next1[i] = nfa.next1[i] = 0;
  413.       sas_nfa.next2[i] = nfa.next2[i] = 0;
  414.       sas_nfa.class[i] = nfa.class[i] = NULL;
  415.    }
  416.  
  417.    /*
  418.     * no macro is executing
  419.     */
  420.    connect_macros( );
  421.  
  422.  
  423.    /*
  424.     * clear the screen and show the author's names
  425.     */
  426.    cls( );
  427.    show_credits( );
  428. }
  429.  
  430.  
  431. /*
  432.  * Name:    hw_initialize
  433.  * Purpose: To initialize the display ready for editor use.
  434.  * Date:    June 5, 1991
  435.  */
  436. void hw_initialize( void )
  437. {
  438. struct vcfg cfg;       /* defined in .h */
  439. register int *clr;
  440.  
  441.    /*
  442.     * set up screen size
  443.     */
  444.    g_display.ncols     = MAX_COLS;
  445.    g_display.nlines    = MAX_LINES - 1;
  446.    g_display.mode_line = MAX_LINES;
  447.    g_display.line_length = MAX_LINE_LENGTH;
  448.  
  449.    /*
  450.     * work out what kind of display is in use, and set attributes and
  451.     *  display address accordingly. Note that this will only work with
  452.     *  close IBM compatibles.
  453.     */
  454.  
  455.    video_config( &cfg );
  456.    g_display.display_address = (char far *)cfg.videomem;
  457.  
  458.    /*
  459.     * Use an integer pointer to go thru the color array for setting up the
  460.     * various color fields.
  461.     */
  462.    clr =  cfg.color == FALSE ? &colour.clr[0][0] : &colour.clr[1][0];
  463.  
  464.    g_display.head_color    = *clr++;
  465.    g_display.text_color    = *clr++;
  466.    g_display.dirty_color   = *clr++;
  467.    g_display.mode_color    = *clr++;
  468.    g_display.block_color   = *clr++;
  469.    g_display.message_color = *clr++;
  470.    g_display.help_color    = *clr++;
  471.    g_display.diag_color    = *clr++;
  472.    g_display.eof_color     = *clr++;
  473.    g_display.curl_color    = *clr++;
  474.    g_display.ruler_color   = *clr++;
  475.    g_display.ruler_pointer = *clr++;
  476.    g_display.hilited_file  = *clr++;
  477.    g_display.overscan      = *clr;
  478.  
  479.    /*
  480.     * set the overscan color.
  481.     * in terminate( ), the overscan color is returned to old state.
  482.     */
  483.    if (g_display.adapter != MDA)
  484.       set_overscan_color( g_display.overscan );
  485. }
  486.  
  487.  
  488. /*
  489.  * Name:    get_help
  490.  * Purpose: save the screen and display key definitions
  491.  * Date:    June 5, 1991
  492.  * Notes:   This routine is dependent on the length of the strings in the
  493.  *          help screen.  To make it easy to load in a new help screen,
  494.  *          the strings are assumed to be 80 characters long followed by
  495.  *          the '\0' character.  It is assumed each that string contains
  496.  *          exactly 81 characters.
  497.  */
  498. int  get_help( WINDOW *window )
  499. {
  500. register char *help;
  501. register int line;
  502.  
  503.    xygoto( -1, -1 );
  504.    help = help_screen[1];
  505.    for (line=0; help != NULL; line++) {
  506.       s_output( help, line, 0, g_display.help_color );
  507.       help = help_screen[line+2];
  508.    }
  509.    line = getkey( );
  510.    redraw_screen( window );
  511.    return( OK );
  512. }
  513.  
  514.  
  515. /*
  516.  * Name:    show_credits
  517.  * Purpose: display authors
  518.  * Date:    June 5, 1991
  519.  */
  520. void show_credits( void )
  521. {
  522. register char *credit;
  523. int  line;
  524.  
  525.    xygoto( -1, -1 );
  526.    credit = credit_screen[0];
  527.    for (line=0; credit != NULL; ) {
  528.       s_output( credit, line+2, 11, g_display.text_color );
  529.       credit = credit_screen[++line];
  530.    }
  531. }
  532.